using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.ComponentModel;

namespace TXLooker.Common.UI
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T">T must be enum</typeparam>
    public class EnumItemDescriptor<T>
    {
        private static Type EnumType = null;

        private static Dictionary<T, EnumItemDescriptor<T>> Map
        {
            get
            {
                if( m_map == null )
                {
                    lock( EnumItemDescriptor<T>.EnumType )
                    {
                        m_map = new Dictionary<T, EnumItemDescriptor<T>>();

                        foreach( T item in Enum.GetValues( EnumItemDescriptor<T>.EnumType ) )
                            m_map.Add( item, new EnumItemDescriptor<T>(item) );
                    }
                }
                return m_map;
            }
        }
        private static Dictionary<T, EnumItemDescriptor<T>> m_map = null;

        static EnumItemDescriptor()
        {
            Type type = typeof(T);

            if( !type.IsEnum )
                throw new Exception( string.Format("Type '{0}' is not Enum type", type.ToString()) );

            EnumItemDescriptor<T>.EnumType = type;            
        }
        private EnumItemDescriptor( T item )
        {
            this.EnumItem = item;

            FieldInfo finfo = EnumItemDescriptor<T>.EnumType.GetField( this.EnumItem.ToString() );

            object[] attributes = finfo.GetCustomAttributes( typeof(DescriptionAttribute), false );
            this.Description = attributes.Length == 0 ? finfo.Name : (attributes[0] as DescriptionAttribute).Description;
        }

        public T EnumItem
        {
            get { return this.m_enumItem; }
            internal set
            {
                this.m_enumItem = value;
            }
        }
        private T m_enumItem = default(T);

        public string Description
        {
            get { return this.m_description; }
            internal set
            {
                if( string.IsNullOrEmpty( value ) )
                    throw new ArgumentException();

                this.m_description = value;
            }
        }
        private string m_description = string.Empty;

        public static EnumItemDescriptor<T>[] Descriptors
        {
            get 
            {
                if( m_descriptors == null )
                {
                    lock( EnumItemDescriptor<T>.EnumType )
                    {
                        if( m_descriptors == null )
                            m_descriptors = ( new List<EnumItemDescriptor<T>>( Map.Values ) ).ToArray();
                    }
                }
                return m_descriptors;
            }
        }
        private static EnumItemDescriptor<T>[] m_descriptors = null;

        public static EnumItemDescriptor<T> GetDescriptor( T item )
        {
            return Map[item];
        }

        public static string DisplayMember
        {
            get { return "Description"; }
        }
    }
}
